package com.towexin.application.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.towexin.application.system.domain.Role;
import com.towexin.application.system.domain.User;
import com.towexin.application.system.domain.UserRole;
import com.towexin.application.system.mapper.UserMapper;
import com.towexin.application.system.service.RoleService;
import com.towexin.application.system.service.UserRoleService;
import com.towexin.application.system.service.UserService;
import com.towexin.utils.ComTool;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author Towexin
 * @version 1.0
 * @date 2021/4/8 14:21
 */
@Service
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
	@Autowired
	private UserMapper mapper;
	@Autowired
	private RoleService roleService;

	@Autowired
	private UserRoleService userRoleService;

	// 添加或修改用户
	@Override
	public boolean saveOrUpdateOne(User user) {
		if (user.getPassword() != null && !"".equals(user.getPassword())) {
			user.setPassword(ComTool.getMD5(user.getPassword()) + ComTool.getMD5(user.getPassword().substring(0, 5)));
		} else {
			user.setPassword(null);
		}
		return this.saveOrUpdate(user);
	}

	// 验证用户名是否重复
	@Override
	public boolean verificationUserName(User user) {
		User u = this.getOne(new QueryWrapper<User>().eq("username", user.getUsername()));
		// 已存在相同用户名
		if (u != null)
			return !u.getId().equals(user.getId()); // 是否本人

		return false; // 用户名不重复，允许操作
	}

	@Override
	public boolean changeStatus(String userName, Boolean status, Integer num) {
		User user = new User();
		user.setStatus(status);
		user.setTryNum(num);

		return update(user, new QueryWrapper<User>().eq("username", userName));
	}

	// 登录操作
	@Override
	public String login(String username, String password, boolean rememberMe) {
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken upt = new UsernamePasswordToken(username,
															  ComTool.getMD5(password) + ComTool.getMD5(password.substring(0, 5)), rememberMe);

		try {
			// upt.setRememberMe(true);
			subject.login(upt);
			return subject.getPrincipal().toString();
		} catch (IncorrectCredentialsException | UnknownAccountException | LockedAccountException e) {
			return e.getMessage();
		}
	}

	// 获取无权操作的用户id
	@Override
	public List<String> noUserIds() {
		Subject subject = SecurityUtils.getSubject();
		// 获取上级角色id（包含关系）
		List<String> rIds = getParentRoleIds(roleService.getByUserName(subject.getPrincipal().toString()).getId(),
				roleService.list());
		// 获取无权操作的用户id
		List<UserRole> userRoles = userRoleService.list(new QueryWrapper<UserRole>().in("r_id", rIds));
		List<String> uIds = new ArrayList<>();

		for (UserRole userRole : userRoles) {
			uIds.add(userRole.getUId());
		}
		return uIds;
	}

	@Override
	public String getNickNameByUserName(String userName) {
		return getOne(new QueryWrapper<User>().eq("username", userName)).getNickname();
	}

	@Override
	public boolean setAllOffline() {
		User user = new User();
		user.setOnline(Boolean.FALSE);
		return update(user, null);
	}

	// 根据id删除
	@Override
	public boolean deleteOne(String id) {
		return this.removeById(id);
	}

	// 分配角色
	@Override
	public boolean setRole(String uId, String rId) {
		UserRole userRole = new UserRole();
		userRole.setUId(uId);
		userRole.setRId(rId);
		return userRoleService.saveOrUpdate(userRole);
	}

	// 根据用户名获取用户(登录时用)
	@Override
	public User selectByUserName(String userName) {
		return this.getOne(
				new QueryWrapper<User>().select("username", "password", "status", "try_num").eq("username", userName));
	}

	// 获取用户分页列表（带模糊查询）
	@Override
	public IPage<Map<String, Object>> selectAndPage(int page, int limit, String nickname) {
		return mapper.selectUserAndRoleAndPage(new Page<>(page, limit), "%" + nickname + "%");
	}

	// 获取角色及上级角色id
	protected List<String> getParentRoleIds(String rId, List<Role> roles) {
		List<String> roleList = new ArrayList<>();
		for (Role role : roles) {
			if (role.getId().equals(rId)) {
				roleList.add(role.getId());
				roleList.addAll(getParentRoleIds(role.getPid(), roles));
			}
		}
		return roleList;
	}
}
